package org.onionframework.faces.model;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.faces.context.FacesContext;

import org.ajax4jsf.model.DataVisitor;
import org.ajax4jsf.model.ExtendedDataModel;
import org.ajax4jsf.model.Range;
import org.ajax4jsf.model.SequenceRange;
import org.onionframework.core.config.SystemConfig;
/**
 * 
 * 抽象的分页数据模型，用于rich:dataTable
 * 
 * @author allan
 *
 * @param <T>
 */
public abstract class PagedDataModel extends ExtendedDataModel<Object> {
	private Integer currentId;
	private Map<Integer, Object> dataMap = new LinkedHashMap<Integer, Object>();
	protected Integer count;
	private int pageSize = SystemConfig.Config.getInt("onion.faces.list.size",15);
	private int lastFirstRow = 0;
	private int lastMaxResults = 0;
	private List<Object> rowKeys = new ArrayList<Object>();
	
	/**
	 * 最终获取总记录数的方法
	 * @return
	 */
	public abstract int getCount();
	
	/**
	 * 最终获取数据的方法
	 * @param firstRow
	 * @param maxResults
	 * @return
	 */
	public abstract List<?> getList(int firstRow, int maxResults);

	@Override
	public Object getRowKey() {
		return this.currentId;
	}

	@Override
	public void setRowKey(Object key) {
		this.currentId = (Integer) key;
	}

	@Override
	public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument){
		int firstRow = ((SequenceRange) range).getFirstRow();
		int maxResults = ((SequenceRange) range).getRows();
		if(maxResults <= 0) maxResults = Integer.MAX_VALUE;
		//数据是不存在
		if(firstRow != this.lastFirstRow || maxResults != this.lastMaxResults) {
			//获取所需数据
			List<?> listRow = this.getList(firstRow, maxResults);
			//记录数据
			dataMap.clear();
			this.rowKeys.clear();
			for(int i = 0; i < listRow.size(); i++) {
				Object row = listRow.get(i);
				int index = firstRow + i;
				this.rowKeys.add(index);
				dataMap.put(index, row);
			}
			
			this.lastFirstRow = firstRow;
			this.lastMaxResults = maxResults;
		}
		//设置数据
		for(Integer index : dataMap.keySet()) {
			visitor.process(context, index, argument);
		}
	}
	
	/*public void modify(List<FilterField> filterFields, List<SortField2> sortFields){
		if(FacesLifecycle.getPhaseId().equals(PhaseId.RENDER_RESPONSE) 
				&& !sortFields.isEmpty()){
			String field;
			this.sortFields = SortProperties.instance();
			for(SortField2 sortField : sortFields){
				if(sortField.getOrdering() == Ordering.UNSORTED)
					continue;
				
				field = sortField.getExpression().getExpressionString();
				field = field.substring(3,field.length() - 2);
				this.sortFields.add(field, Ordering.ASCENDING == sortField.getOrdering() ? SortType.ASC : SortType.DESC);
			}
			this.lastFirstRow = -1;
		}
	}*/

	@Override
	public int getRowCount() {
		if(count == null)
			count = this.getCount();
		return count;
	}
	
	@Override
	public boolean isRowAvailable() {
		if(dataMap == null) {
			return false;
		} else {
			return dataMap.containsKey(currentId);
		}
	}

	@Override
	public Object getRowData() {
		return dataMap.get(currentId);
	}
	
	@Override
	public Object getWrappedData() {
		return this.getList(0, Integer.MAX_VALUE);
	}

	@Override
	public void setWrappedData(Object arg0) {
		throw new UnsupportedOperationException();
	}
	
	@Override
	public int getRowIndex() {
		return this.rowKeys.indexOf(this.getRowKey());
	}

	@Override
	public void setRowIndex(int index) {
		this.setRowKey(this.rowKeys.get(index));
	}

	/**
	 * @return the pageSize
	 */
	public int getPageSize() {
		return this.pageSize;
	}
}
